package com.game.fg.service;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft_6455;
import org.java_websocket.handshake.ServerHandshake;
import org.json.JSONObject;

import java.net.URI;
import java.net.URISyntaxException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Enumeration;

class ManagerServer {

    private WebSocketClient ws;
    private static Logger logger = LogManager.getLogger(ManagerServer.class.getName());

    public WebSocketClient getWs() {
        return ws;
    }

    static class ServerInfo {
        short gameID;//游戏ID
        short serverID;//服务器ID
        short serverLevel;//服务器等级
        short serverPort;//服务器端口
        int minScore;//进房间最大积分要求
        int maxScore;//进房间最小积分要求
        int maxPlayer;//房间最大人数
        int firstTax;
        int secondTax;
        String serverName;
        String serverIP;
        short serverStatus;//服务器状态

        ServerInfo() {
        }
    }

    static ServerInfo serverInfo = new ServerInfo();//服务器信息

    void start(String url) {
        try {
            ws = new WebSocketClient(new URI(url), new Draft_6455()) {
                @Override
                public void onMessage(String message) {
                    logger.debug("onMessage(String message)");
                }

                @Override
                public void onMessage(ByteBuffer blob) {
                    byte identity = blob.get(0);
                    byte encode = blob.get(1);
                    short length = blob.getShort(2);
                    byte version = blob.get(4);
                    byte reserve = blob.get(5);
                    short cmd = blob.getShort(6);
                    byte[] data = new byte[length - 8];
                    System.arraycopy(blob.array(), 8, data, 0, length - 8);
                    if (cmd > 0) {
                        msgParse(cmd, data);
                    }
                }

                @Override
                public void onOpen(ServerHandshake handshake) {
                    logger.debug("管理服务器连接成功");
                    preRegister();
                    register();
                }

                @Override
                public void onClose(int code, String reason, boolean remote) {
                    logger.debug("管理服务器连接断开");
                }

                @Override
                public void onError(Exception ex) {
                    ex.printStackTrace();
                }
            };
            ws.connect();
        } catch (URISyntaxException ex) {
            ex.printStackTrace();
        }
    }

    //向管理服务器预注册
    private void preRegister() {
        ByteBuffer bb = ByteBuffer.allocate(8);
        bb.order(ByteOrder.LITTLE_ENDIAN);
        bb.putInt(serverInfo.serverID);//iServerID
        bb.putInt(serverInfo.gameID);//iGameID
        FGWebSocket.sendCustom(ws, 0xFEFE, bb.array());
        logger.debug(String.format("向管理服务器预注册 serverID:%d gameID:%d", serverInfo.serverID, serverInfo.gameID));
    }

    //向管理服务器注册游戏信息
    private void register() {
        ByteBuffer bb = ByteBuffer.allocate(204);
        bb.order(ByteOrder.LITTLE_ENDIAN);
        bb.putShort(serverInfo.serverID);//iServerID
        bb.putShort(serverInfo.gameID);//iGameID
        bb.putShort(serverInfo.serverPort);//电信端口
        bb.putShort((short) 0);//网通端口777
        bb.putInt(100);//iMaxTableNum
        bb.putInt(1);//iChairNum
        bb.putInt(serverInfo.maxPlayer);//iMaxPlayerNum
        bb.putInt(0);//iOnline
        bb.putInt(0);//ulLimitPoint
        bb.putInt(0);//iUpLimitCoin
        bb.putInt((byte) serverInfo.serverLevel);//cRoomLevel
        bb.putInt(0);//ulBaseTime
        bb.put((byte) 1);//ucServerType
        bb.put((byte) serverInfo.serverStatus);//bOpenFlag
        String gameIP = serverInfo.serverIP;//IP
        String gameHash = "";//应用的hashcode
        String gameName = serverInfo.serverName;//游戏名称
        String roomName = "";//房间名称
        String dnsInfo = "www";//域名信息
        byte[] bGameIP = new byte[32];
        byte[] bGameHash = new byte[32];
        byte[] bGameName = new byte[32];
        byte[] bRoomName = new byte[32];
        byte[] bDnsInfo = new byte[32];
        System.arraycopy(gameIP.getBytes(), 0, bGameIP, 0, gameIP.length());
        System.arraycopy(gameHash.getBytes(), 0, bGameHash, 0, gameHash.length());
        System.arraycopy(gameName.getBytes(), 0, bGameName, 0, gameName.length());
        System.arraycopy(roomName.getBytes(), 0, bRoomName, 0, roomName.length());
        System.arraycopy(dnsInfo.getBytes(), 0, bDnsInfo, 0, dnsInfo.length());
        bb.put(bGameIP);
        bb.put(bGameHash);
        bb.put(bGameName);
        bb.put(bRoomName);
        bb.put(bDnsInfo);
        FGWebSocket.sendCustom(ws, 0xB1, bb.array());
        logger.debug(String.format("向管理服务器注册游戏信息 gameID:%d serverID:%d serverIP:%s serverPort:%d serverStatus:%d maxPlayer:%d",
                serverInfo.gameID,
                serverInfo.serverID,
                gameIP,
                serverInfo.serverPort,
                serverInfo.serverStatus,
                serverInfo.maxPlayer));
    }

    //同步在线信息
    void updateOnline(int onlineNum) {
        if (ws != null && ws.isOpen()) {
            ByteBuffer bb = ByteBuffer.allocate(12);
            bb.order(ByteOrder.LITTLE_ENDIAN);
            bb.putInt(serverInfo.serverID);//iServerID
            bb.putInt(onlineNum);//iOnLineNum
            bb.putInt(1);//bOpenFlag
            FGWebSocket.sendCustom(ws, 0xB3, bb.array());
            logger.debug(String.format("同步在线人数:%d", onlineNum));
        }
    }

    //心跳包
    void KeepAlive() {
        if (ws != null && ws.isOpen()) {
            FGWebSocket.sendCustom(ws, FGConst.CMD_KEEP_ALIVE, new byte[]{});
        }
    }

    private void msgParse(int cmd, byte[] data) {
        ByteBuffer bb = ByteBuffer.allocate(data.length);
        bb.order(ByteOrder.LITTLE_ENDIAN);
        bb.put(data);
        bb.rewind();
        switch (cmd) {
            case FGConst.M2S_MsgNotice: {
                int eventID = bb.getInt();
                int gameID = bb.getInt();
                int serverID = bb.getInt();
                int userID = bb.getInt();
                byte[] content = new byte[512];
                bb.get(content);
                if (eventID == 1004) {
                    //公告
                    JSONObject jsonContent = new JSONObject(new String(content).trim());
                    JSONObject properties = jsonContent.getJSONObject("properties");
                    String msg = properties.getString("value");
                    Enumeration e = FGUserManager.getInstance().getUserMap().elements();
                    while (e.hasMoreElements()) {
                        FGUser user = (FGUser) e.nextElement();
                        FGWebSocket.send(user.getWs(), FGConst.S2C_SystemNotice, MessageBuild.systemNotice(msg));
                    }
                    logger.debug(String.format("系统公告:%s", msg));
                } else if (eventID == 1021) {
                    //踢人
                    FGUser user = FGUserManager.getInstance().getUser(userID);
                    if (user != null) {
                        FGWebSocket.send(user.getWs(), FGConst.S2C_KickOff, MessageBuild.kickOff());
                        FGUserManager.getInstance().removeUser(userID, "系统踢除");
                        logger.debug("系统踢除玩家 uid:" + userID);
                    }
                }
                logger.debug(String.format("系统消息 eventID:%d gameID:%d serverID:%d userID:%d", eventID, gameID, serverID, userID));
            }
            break;

        }
    }

    private ManagerServer() {
    }

    private static ManagerServer ms = new ManagerServer();

    public static ManagerServer getInstance() {
        return ms;
    }
}
